Redis 学习路线
介绍
很多同学第一次接触 Redis 可能都是因为 “缓存”,也有很多同学误以为 Redis 就是缓存、只能做缓存。
事实上,Redis 是知名的高性能内存 K / V 存储系统,除了缓存之外,Redis 还可以用作配置存储、消息队列、解决分布式一致性问题等。正因为 Redis 的高性能、通用性、易用性、功能强大,使得它成为了后端开发中必不可少的中间件。
只要你的学习方向是后端开发,就必须要系统地学习 Redis。不仅要学会应用到项目中,还要学习它优秀的系统设计以及实现原理,可以开拓我们开发程序、解决问题的思路。
学习条件
- 目标方向是后端开发或数据库、数据开发相关的岗位(前端同学先不要学了)
- 先学完一套开发框架(比如 SSM、SpringBoot),再学习 Redis
学习路线
建议大家按照以下五个阶段来学习:
- 基础入门
- 实战应用
- 高阶知识
- 底层原理
- 备战面试
知识点
- 一、基础入门
- Redis 是什么?
- SQL 和 NoSQL
- Redis 特点
- Redis 安装
- 连接方式
- 常用命令
- 通用命令
- 命令手册
- 基本数据结构
- String
- Hash
- List
- Set
- SortedSet
- Redis 管理工具
- Redis Insight
- Quick Redis
- RESP
- Redis 客户端及用法
- Jedis
- Spring Data Redis
- Redisson
- Lettuce
- 二、实战应用
- 分布式 Session
- 高级数据结构
- GEO(地理位置计算)
- Bitmap(实现签到)
- HyperLogLog(实现 U / V 统计)
- Bloom Filter
- 消息队列
- Pub/Sub
- Stream
- 缓存
- 缓存更新
- Cache Aside 模式
- Read / Write Through 模式
- Write Behind 模式
- 缓存问题及解决方案
- 缓存穿透
- 缓存击穿
- 缓存雪崩
- 多级缓存
- 缓存预热
- 缓存更新
- 分布式全局唯一 id 生成
- Lua 脚本(实现秒杀)
- 分布式锁 Redisson 实现
- Feed 流实现
- 事务
- 三、高阶知识
- Redis 最佳实践
- 键值设计
- 客户端优化
- 服务端优化
- 数据持久化
- RDB
- AOF
- 两者对比
- 主从同步
- 全量同步
- 增量同步
- 主从集群优化
- 哨兵集群
- 介绍和特点
- 故障转移
- 分片集群
- 介绍和特点
- 散列插槽
- 集群伸缩
- 故障转移
- 数据迁移
- Redis 最佳实践
- 四、底层原理
- 底层数据结构
- 动态字符串
- IntSet
- Dict
- ZipList
- SkipList
- Redis Object
- 五种基本数据结构的底层
- Redis 网络模型
- 阻塞 I / O
- 非阻塞 I / O
- I / O 多路复用
- Redis 线程模型
- Redis 通信协议
- Redis 内存淘汰策略
- 底层数据结构
- 五、备战面试
学习资源
1、入门教程(从这里开始)
直接看这套视频课程即可一条龙入门:https://www.bilibili.com/video/BV1cr4y1671t
几乎包括了 Redis 所有入门知识和主流应用、还有高级用法和原理的讲解,强烈推荐。
除了视频学习之外,还可以配合《图解 Redis》文档食用:https://xiaolincoding.com/redis/
2、项目实战
Redis 项目推荐及笔记:https://t.zsxq.com/07JMnQvne
3、可视化工具
Redis Insight:https://redis.io/docs/stack/insight/
Quick Redis:https://quick123.net/
4、命令手册
Redis 官网命令集:https://redis.io/commands (命令忘了就查)
中文版命令集:http://www.redis.cn/commands.html
5、经典面试题
视频 1:https://www.bilibili.com/video/BV1Ni4y1Q7XM/
视频 2:https://www.bilibili.com/video/BV1BB4y1y7M2
视频 3:https://www.bilibili.com/video/BV1it4y1W7D1
常见面试题整理(by 小林):https://xiaolincoding.com/redis/base/redis_interview.html
学习建议
- Redis 是一个注重实际运用的技术,在学习 Redis 的过程中,要记得多敲命令 / 多写代码来操作 Redis,将 Redis 实际运用到你之前做过的项目中,而不是死记硬背。尤其是不要去背命令和代码,忘了就查、多写几次后印象自然就深刻了。
- 对于初学后端的同学来说,学完第二阶段(实战应用)后就可以再去学消息队列、微服务等其他知识了。等主流的后端开发技术都会用后、面试前再回过头来补高级知识和原理即可。
- Redis 的最佳实践部分要重点学习,建议是整理笔记便于自己复习查阅。争取养成好的设计和编码习惯,对以后的工作发展会很有帮助。
实操干货:把高频命令敲一遍
上面路线列的是"学什么",这一节补"怎么用"——都是我实际用得最多的东西,忘了就回来查。
连接与通用命令
# 本机默认 6379 直接进;远程加 -h -p,有密码进交互后 AUTH 输入(-a 会把密码留在 shell 历史里)
redis-cli
redis-cli -h 127.0.0.1 -p 6379
# 通用命令:跟 key 本身打交道,跟类型无关
SET name "redis" # 写
GET name # 读
EXISTS name # 判断是否存在,返回 1/0
DEL name # 删除
TYPE name # 看类型:string / hash / list / set / zset
KEYS * # 列出所有 key——只在玩具库用!生产是 O(N) 全库遍历,会卡死
SCAN 0 MATCH user:* COUNT 100 # 生产用 SCAN 渐进遍历:游标从 0 开始,返回 0 才是遍历完
DBSIZE # key 总数
FLUSHDB # 清空当前库——生产环境远离这条命令
💡 Redis 默认 16 个库(0~15),
SELECT 1切换。但注意:集群模式下只有 db0 一个库,别把业务隔离寄托在多库上。
五大类型:命令实操
String —— 缓存、计数、分布式锁的底座:
SET user:1:name "张三"
SET counter 100
INCR counter # 原子自增:阅读量、限流计数都靠它
INCRBY counter 50 # 自增 50
SET lock:order:1 "uuid-xxx" NX EX 10 # 不存在才写 + 10 秒过期:最简版分布式锁
MSET k1 v1 k2 v2 # 批量写
MGET k1 k2 # 批量读,省 N 次网络往返
Hash —— 对象缓存首选,比整个对象 JSON 序列化进 String 好改单个字段:
HSET user:1 name "张三" age 21 level 3 # 多个 field 一次写
HGET user:1 name
HGETALL user:1 # 全取(field 上千的大对象慎用,改用 HMGET 指定取)
HDEL user:1 level
HEXISTS user:1 age # 判断 field 是否存在
List —— 消息队列、最新列表:
LPUSH news:latest "a" "b" "c" # 左进
LRANGE news:latest 0 4 # 取前 5 条;-1 表示末尾
RPOP news:latest # 右出(LPUSH + RPOP 就是一个简单队列)
LLEN news:latest # 长度
BRPOP news:latest 5 # 阻塞式右出:5 秒内没数据就等着,比轮询 RPOP 优雅
Set —— 去重、抽奖、共同关注:
SADD lottery "张三" "李四" "王五"
SISMEMBER lottery "张三" # 是否在里面(去重判断)
SRANDMEMBER lottery 2 # 随机看 2 人(不取出);SPOP 是抽出即移除
SCARD lottery # 元素个数
SINTER follow:a follow:b # 交集:共同关注
SUNION follow:a follow:b # 并集
SDIFF follow:a follow:b # 差集:a 关注了但 b 没关注
ZSet —— 排行榜,直接按分数排好序:
ZADD rank 95 "张三" 87 "李四" 92 "王五"
ZINCRBY rank 5 "李四" # 加分
ZREVRANGE rank 0 9 WITHSCORES # 前 10 名(分数从高到低)
ZREVRANK rank "李四" # 某人排第几
ZRANGEBYSCORE rank 90 100 # 取 90~100 分区间
ZCARD rank # 总人数
TTL 与过期
EXPIRE user:1:name 60 # 60 秒后过期
TTL user:1:name # 还剩几秒;-1 永不过期,-2 key 已不存在
PERSIST user:1:name # 取消过期
SET code "6666" EX 300 NX # 写入时直接带过期 + 不存在才写:验证码标准写法
两个我踩过的坑:
- 对一个已有 TTL 的 key 再执行
SET,过期时间会被清掉变回永久 key。想保住 TTL 要用SET key value KEEPTTL(Redis 6.0+),或者重新 EXPIRE 一次。 - 过期是"惰性删除 + 定期抽样删除"的组合:key 到期不一定立刻物理消失,但 GET 不到了。内存吃紧时靠淘汰策略兜底(maxmemory-policy,常用 allkeys-lru)。
缓存三兄弟:穿透 / 击穿 / 雪崩
三个问题的共同点是"缓存不在了,请求全砸到数据库",但成因不同,解法也不同:
| 问题 | 成因 | 解法 |
|---|---|---|
| 缓存穿透 | 查根本不存在的数据,缓存永远不命中 | 缓存空值(短 TTL)+ 布隆过滤器兜底 + 入参合法性校验 |
| 缓存击穿 | 一个热点 key 过期的瞬间,海量请求直击数据库 | 互斥锁(只放一个请求去回源)+ 热点数据用逻辑过期不真删 |
| 缓存雪崩 | 大批 key 同时过期(或 Redis 宕机),数据库被瞬间打爆 | 过期时间加随机值打散 + 多级缓存 + 集群高可用 + 限流降级 |
配合 Cache Aside 模式的标准读法:
import json
import random
def get_user(uid):
key = f"user:{uid}"
val = r.get(key)
if val is not None:
return json.loads(val)
# 缓存没有 → 查库
user = db.query(User).get(uid)
if user is None:
# 穿透防护:空结果也缓存,短 TTL,挡住恶意 id 反复打库
r.set(key, "", ex=60)
return None
# 雪崩防护:过期时间加随机,避免同批 key 一起死
r.set(key, json.dumps(user), ex=3600 + random.randint(0, 300))
return user
写路径一句话:先更新数据库,再删缓存(不是更新缓存)——删除让下次读自然回源,避免并发写把旧值写回缓存。这就是 Cache Aside 模式的全部。
持久化:RDB vs AOF 速记
| RDB | AOF | |
|---|---|---|
| 记什么 | 某一时刻的全量快照(二进制) | 每条写命令追加进日志 |
| 触发 | save(阻塞主线程,别用)/ bgsave(fork 子进程) | appendfsync always / everysec / no |
| 恢复速度 | 快(直接载入二进制) | 慢(逐条重放命令) |
| 数据安全 | 两次快照之间的数据会丢 | everysec 最多丢 1 秒 |
| 代价 | fork 瞬间可能卡顿 | 文件大,需要重写机制(bgrewriteaof)压缩 |
两者不是二选一:生产标配是 RDB + AOF 混合持久化(Redis 4.0+,aof-use-rdb-preamble yes)——恢复用 RDB 打底保证速度,丢数据按 AOF 标准算保证安全。
Python 实战:redis-py 三板斧
pip install redis
连接:decode_responses=True 是第一个坑:
import redis
# 不加 decode_responses=True,拿到的全是 bytes,每个都要自己 .decode()
r = redis.Redis(host="localhost", port=6379, db=0, decode_responses=True)
# 服务里建议显式用连接池
pool = redis.ConnectionPool(host="localhost", port=6379,
max_connections=50, decode_responses=True)
r = redis.Redis(connection_pool=pool)
日常操作直接对应命令名:
r.set("user:1:name", "张三", ex=3600) # 命令叫 SET,方法就是 r.set,参数同理
name = r.get("user:1:name")
r.hset("user:1", mapping={"name": "张三", "age": 21}) # Hash 批量写
user = r.hgetall("user:1") # 返回 dict
r.incr("counter") # 原子自增
r.expire("user:1", 60) # 补 TTL
r.exists("user:1") # 判断
r.delete("user:1") # 删除
Pipeline:把 N 次往返合成 1 次:
# 循环里一条条 set,1000 个 key 就是 1000 次网络往返——很慢
pipe = r.pipeline()
for i in range(1000):
pipe.set(f"k:{i}", i, ex=3600)
pipe.execute() # 一次性打包发送,快一个数量级
💡 简易分布式锁的坑:
r.set(lock_key, token, nx=True, ex=10)这一行里 NX 和 EX 必须在同一条命令里写。先 SETNX 再 EXPIRE 是两步,中间进程一挂,锁就永远不过期——经典事故。
进阶数据类型:Bitmap / HyperLogLog / GEO
路线篇"实战应用"阶段列的三个高级结构,补上命令体感——它们的共同思路是用极小的内存解决特定统计问题。
Bitmap —— 签到打卡:
SETBIT sign:user:1:202608 14 1 # 用户 1 在 8 月第 15 天签到(位从 0 数起)
GETBIT sign:user:1:202608 14 # 查某天是否签到
BITCOUNT sign:user:1:202608 # 本月签到总天数
一年签到 = 365 bit ≈ 46 字节。一亿用户的签到也就几百 MB——这是"按位存布尔"的威力。连续签到的判断配合 BITPOS 找第一个 0。
HyperLogLog —— 海量去重计数(UV 统计):
PFADD uv:20260831 "user:1" "user:2" "user:3"
PFCOUNT uv:20260831 # 去重计数,标准误差约 0.81%
PFMERGE uv:202608 uv:20260829 uv:20260830 # 合并出整月 UV
固定约 12KB 内存就能数亿级 UV,还能任意合并。代价是:拿不到名单,只知道"大概有多少个不重复的"——要数就别用 Set 存全量,这是书里反复强调的取舍。
GEO —— 附近的人 / 附近的店:
GEOADD shops 121.47 31.23 "门店A" 121.48 31.24 "门店B"
GEOSEARCH shops FROMLONLAT 121.47 31.23 BYRADIUS 2000 m ASC COUNT 5 # 2km 内最近 5 家
💡 GEO 底层就是 ZSet(经纬度编码进了 score)——所以 ZSet 那套 ZRANGEBYSCORE 的思路对它部分通用,理解成本低。
消息队列三方案:List / Pub/Sub / Stream
| 方案 | 命令 | 优点 | 硬伤 |
|---|---|---|---|
| List 队列 | LPUSH + BRPOP | 简单够用 | 无 ack:消费者取走就没了,处理崩溃消息即丢 |
| Pub/Sub | PUBLISH / SUBSCRIBE | 实时广播多订阅者 | 不持久化:订阅者掉线期间的消息全丢 |
| Stream | XADD / XREADGROUP / XACK | 消费组 + ack + 持久化,像简化版 Kafka | 略复杂,功能仍不及专业 MQ |
Stream 消费组的最小骨架(消息不丢的关键是 XACK):
XADD orders * item "book" price 59 # * 表示让 Redis 自动生成消息 ID
XGROUP CREATE orders g1 0 # 建消费组 g1,从 0 开始消费
XREADGROUP GROUP g1 consumer1 COUNT 10 BLOCK 5000 STREAMS orders >
XACK orders g1 1693-0 # 处理完确认;没 ack 的留在 PEL 里可重投
我的记忆锚点:要丢得起就用 List/Pub-Sub(简单),丢不起就上 Stream(ack 兜底);再往上要求事务消息、堆积管理,那是专业 MQ(RocketMQ/Kafka)的地盘,别硬用 Redis 扛。
高可用速记:主从 / 哨兵 / 分片集群
| 形态 | 解决什么 | 关键点 |
|---|---|---|
| 主从复制 | 读扩容 + 数据热备 | 首次全量同步(bgsave RDB 传从库)+ 之后增量(repl_backlog 环形缓冲);写永远走主 |
| 哨兵集群 | 主挂了自动切换 | 监控 + 主观/客观下线判定 + Raft 式选主 + 通知客户端新主地址 |
| 分片集群 | 写扩容 + 海量数据 | 16384 个哈希槽,按 key 的 CRC16 取模分槽;水平扩容=迁移槽 |
三层各管一件事:主从解决"读",哨兵解决"高可用",分片解决"写和数据量"。设计时按这个顺序自查需求:读压力大→加从库;怕单点→上哨兵;写也扛不住/数据太大→分片集群。
⬅️ 00-NoSQL 数据库总览 🏠 00-数据库 ➡️ 02-Redis 核心数据结构与命令
💬 评论